﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DirectShowLib;
using DirectShowLib.DES;
using System.Runtime.InteropServices;
using System.IO;
using System.Drawing;
using System.Text.RegularExpressions;

namespace GBPVRLibrary.MetadataLibrary
{
    public class VideoFileInformation
    {
        public float FrameRate { get; private set; }
        public TimeSpan Duration { get; private set; }
        public int Width { get; private set; }
        public int Height { get; private set; }
        public double FrameCount { get; private set; }

        public int AudioChannels { get; private set; }
        public int AudioSamplesPerSecond { get; private set; }

        public VideoFileInformation(string Filename)
        {
            if(Regex.IsMatch(Filename, @"\.(iso|bin|cue|img)$", RegexOptions.IgnoreCase))
                return;
            AMMediaType mediaType = null;
            try
            {
                FileInfo fi = new FileInfo(Filename);
                if (!fi.Exists)
                    throw new Exception("File doesn't exist");
                IMediaDet mediaDet = (IMediaDet)new MediaDet();
                DsError.ThrowExceptionForHR(mediaDet.put_Filename(Filename));

                // find the video stream in the file
                int index = 0;
                Guid type = Guid.Empty;
                int NumberOfStreams = 0;
                mediaDet.get_OutputStreams(out NumberOfStreams);
                string test = DirectShowLib.MediaType.Video.ToString();
                while (index < NumberOfStreams)
                {
                    mediaDet.put_CurrentStream(index++);
                    mediaDet.get_StreamType(out type);
                    if (type == DirectShowLib.MediaType.Video)
                        break;
                }

                if (type == DirectShowLib.MediaType.Video)
                {
                    // retrieve some measurements from the video
                    double frameRate;
                    mediaDet.get_FrameRate(out frameRate);
                    this.FrameRate = (float)frameRate;

                    mediaType = new AMMediaType();
                    mediaDet.get_StreamMediaType(mediaType);

                    VideoInfoHeader videoInfo = (VideoInfoHeader)Marshal.PtrToStructure(mediaType.formatPtr, typeof(VideoInfoHeader));
                    DsUtils.FreeAMMediaType(mediaType);
                    mediaType = null;
                    this.Width = videoInfo.BmiHeader.Width;
                    this.Height = videoInfo.BmiHeader.Height;

                    double mediaLength;
                    mediaDet.get_StreamLength(out mediaLength);
                    this.Duration = TimeSpan.FromSeconds(mediaLength);
                    this.FrameCount = (int)(frameRate * mediaLength);
                }
                                
                // find the audio info
                index = 0;
                type = Guid.Empty;
                while (index < NumberOfStreams)
                {
                    mediaDet.put_CurrentStream(index++);
                    mediaDet.get_StreamType(out type);
                    if (type == DirectShowLib.MediaType.Audio)
                        break;
                }
                if (type == DirectShowLib.MediaType.Audio)
                {
                    mediaType = new AMMediaType();
                    mediaDet.get_StreamMediaType(mediaType);
                    WaveFormatEx audioInfo = (WaveFormatEx)Marshal.PtrToStructure(mediaType.formatPtr, typeof(WaveFormatEx));
                    DsUtils.FreeAMMediaType(mediaType);
                    mediaType = null;

                    this.AudioChannels = audioInfo.nChannels;
                    this.AudioSamplesPerSecond = audioInfo.nSamplesPerSec;
                }
            }
            catch (Exception ex)
            {
                string error = ex.Message;
            }
            finally
            {
                if (mediaType != null)
                {
                    DsUtils.FreeAMMediaType(mediaType);
                }
            }   
        }
    }
}
